#coding:utf8
#
# Author: CMGS
# Created on 2010-9-15
#

from common import config as _config
from common import defcode as _defcode
from utils.cron import PeriodicCallback
from libs import klive as _klive
from libs.rpc import rpc as _rpc
from libs.session import sessionPool as _sessionPool
from appuser.apiuser import autoCleaner
from appmsg.apimsg import update as _update
from appcontrol import apicontrol as _apicontrol
from appuser import apiuser

class Join(object):
    
    def __init__(self):
        self.SHARERS = 0
        self.OWNER = 1
        self.FORBIDDEN = 2

    def newJoin(self, fileHash, token):
        # check token
        if token == '' or len(token) < 40:
            return _rpc.toJson({'code': _defcode.OPT_FAILED, 'reason': 'invaild token'})
        # check user permission
        checkUser = self._checkUser(fileHash, token)
        if checkUser == self.FORBIDDEN:
            return _rpc.toJson({'code': _defcode.OPT_FAILED, 'reason': 'forbidden to this file'})
        # get user info
        userInfo = self._getUserInfo(token)
        # single login
        ret, isJoined = self._singleJoin(fileHash, userInfo)
        if isJoined:
            return _rpc.toJson(ret)
        # create session
        sid, sessions = _sessionPool.createSession(fileHash)
        # check autoincrease number
        count = sessions.get(_config.MEM_AUTOINC_NAME, 0)
        # get sid
        ret['sid'] = sid
        # get user type
        if checkUser == self.OWNER:
            sessions[sid][_config.MODIFY_NO_NAME] = 0
            ret[_config.MODIFY_NO_NAME] = 0
        else:
            count += 1
            sessions[sid][_config.MODIFY_NO_NAME] = count
            ret[_config.MODIFY_NO_NAME] = count
            sessions[_config.MEM_AUTOINC_NAME] = count
        sessions[sid][_config.MODIFY_VECTOR_NAME] = 0
        sessions[sid]['userId'], sessions[sid]['username'] = userInfo
        ret['userId'] = sessions[sid]['userId']
        ret['username'] = sessions[sid]['username']
        # add auto corn
        if not sessions.has_key(_config.AUTO_REFRESH_TIME):
            sessions[_config.MEM_CRON_NAME] = PeriodicCallback(autoCleaner, _config.AUTO_REFRESH_TIME, True, fileHash)
        _apicontrol.cleanLogoutMsg(sessions, sessions[sid]['username'])
        _update(fileHash, sid, _rpc.toJson({'type':'login', 'username': sessions[sid]['username'], _config.MODIFY_NO_NAME: sessions[sid][_config.MODIFY_NO_NAME]}))
        ret[_config.MODIFY_VECTOR_NAME], ret['users'] = self._makeRetData(sessions)
        del ret['users'][ret['userId']]
        return _rpc.toJson(ret)

    def closeJoin(self, fileHash, sid):
        session = _sessionPool.getSession(fileHash, sid)
        if session is not None:
            # clean login msg            
            _apicontrol.cleanLoginMsg(_sessionPool.getSessions(fileHash), int(session[_config.MODIFY_NO_NAME]))
            _update(fileHash, sid, _rpc.toJson({'type':'logout', 'username': session['username'], _config.MODIFY_NO_NAME: session[_config.MODIFY_NO_NAME]}))
            _sessionPool.removeSession(fileHash, sid)
            return _rpc.toJson({'code': _defcode.OPT_OK})
        return _rpc.toJson({'code': _defcode.OPT_FAILED, 'reason': 'no user'})

    def _getSid(self, sessions, uId, name):
        for sid in sessions.keys():
            if sid in _config.UNSID_KEY:                
                continue
            if sessions[sid]['userId'] == uId and sessions[sid]['username'] == name:
                return sid
        return None

    def _singleJoin(self, fileHash, userInfo):
        uId, name = userInfo
        ret = {}
        sessions = _sessionPool.getSessions(fileHash)
        if sessions is None:
            return ret, False
        sid = self._getSid(sessions, uId, name)
        if sid is None or not sessions.has_key(sid):
            return ret, False
        session = sessions[sid]
        # update time
        if _rpc.loadJson(apiuser.keepOnline(fileHash, sid))['code'] != _defcode.OPT_OK:
            return ret, False
        ret['sid'] = sid
        ret['userId'] = session['userId']
        ret['username'] = session['username']
        ret[_config.MODIFY_NO_NAME] = session[_config.MODIFY_NO_NAME]
        ret[_config.MODIFY_VECTOR_NAME], ret['users'] = self._makeRetData(sessions)
        del ret['users'][ret['userId']]
        # clean login msg
        _apicontrol.cleanLoginMsg(sessions, int(session[_config.MODIFY_NO_NAME]))
        # update new msg
        _update(fileHash, sid, _rpc.toJson({'type':'login', 'username': session['username'], _config.MODIFY_NO_NAME: session[_config.MODIFY_NO_NAME]}))
        return ret, True

    def _makeRetData(self, sessions):
        v = {}
        i = {}
        for sid in sessions.keys():
            if sid in _config.UNSID_KEY:
                continue
            no = sessions[sid][_config.MODIFY_NO_NAME]
            value = sessions[sid][_config.MODIFY_VECTOR_NAME]
            userId = sessions[sid]['userId']
            username = sessions[sid]['username'] 
            i[userId] = username
            v[no] = value
        return v, i

    def _getUserInfo(self, token):
        params = {'token': token}
        ret = _klive.getApiData('getUserInfo', params, 2)
        if ret == {} or ret.has_key('reason'):
            return None, None
        userId = ret['userId']
        username = ret['username']
        return userId, username

    def _checkUser(self, hash, token):
        # getItemInfo
        params = {'token': token, 'fileId': hash}
        ret = _klive.getApiData('getItemInfo', params, 2)
        if ret == {} or ret.has_key('reason'):
            return self.FORBIDDEN
        fileId = ret['fileId']
        # getShareFiless
        params = {'token': token, 'type': 'toMe'}
        ret = _klive.getApiData('asmGetAllSharedFiles', params)
        if isinstance(ret['file'], dict):
            fileList = [ret['file']]
        else:
            fileList = ret['file']
        if ret != {}:
            toMeFileIdSet = [file['fileId'] for file in fileList]
            if fileId in toMeFileIdSet:
                return self.SHARERS
        return self.OWNER

join = Join()
newJoin = join.newJoin
closeJoin = join.closeJoin

if __name__ == '__main__':
    params = {'user': 'dengjian@kingsoft.com', 'password': '41206623', 'deviceId': 'test-pc', 'clientName': 'test-pc', 'clientVersion' : '1.0.0'}
    ret = _klive.getApiData('login', params, 2)
    print ret
    print join._checkUser('689539819503622', ret['token'])
    print join._getUserInfo(ret['token'])
